package com.newy.dao.sys;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.newy.core.hibernate.HibernateDao;
import com.newy.domain.sys.Menu;
import com.newy.domain.sys.Menu.MenuType;


@Repository
public class MenuDao extends HibernateDao<Menu, Long> {
	/**
	 * 获取所有菜单，按父ID、排序号排序
	 */
	public List<Menu> getAll(){
		return this.getAll(Order.asc("parentId"), Order.asc("sortNum"));
	}
	
	/**
	 * 级联删除菜单，返回所有被删除菜单的id
	 */
	public Set<Long> deleteCascade(Long id){
		return this.deleteCascade(id, "parentId");
	}

	/**
	 * 级联删除菜单，返回所有被删除菜单的id
	 */
	public Set<Long> deleteCascade(Menu menu){
		return this.deleteCascade(menu, "parentId");
	}
	
	/**
	 * 通过指定的父id和类型查找子记录，如果类型为空则查找所有类型
	 */
	public List<Menu> getChildren(Long parentId, MenuType... types){
		List<Criterion> criterions = new ArrayList<Criterion>(2);
		criterions.add(parentId != null ? Restrictions.eq("parentId", parentId) : Restrictions.isNull("parentId"));
		if (types.length > 0){ //指定类型
			criterions.add(Restrictions.in("type", types));
		}
		return this.find(criterions, Order.asc("sortNum"));
	}
	
	public boolean hasChildren(Long parentId){
		return this.exists("parentId", parentId);
	}
	
	public String getIdPath(Long id){
		List<Long> ids = new ArrayList<Long>();
		Menu menu = this.get(id);
		while(true){
			if (menu != null){
				ids.add(0, menu.getId());
			}
			else{
				break;
			}
			menu = this.get(menu.getParentId());
		}
		return StringUtils.join(ids, "/");
	}
	
	/**
	 * 获取所有与用户关联的菜单，菜单按父ID、排序号排序
	 */
	public List<Menu> getMenusOfUser(Long userId){
		String hql = "select distinct m from Menu m, RoleMenu rm, RoleUser ru" +
				" where m.id=rm.menuId and rm.roleId=ru.roleId and ru.userId=?" +
				" order by m.parentId, m.sortNum";
		return this.find(hql, userId);
	}
}
